package com.czk.stack;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/6/20 15:05
 */
public class ArithmeticExpression {
    public static void main(String[] args) {
        String str="30+2*6-2";
        ArrayStack2 numStack=new ArrayStack2(10);
        ArrayStack2 operStack=new ArrayStack2(10);
        // 定义扫描索引
        int index=0;
        int num1=0,num2=0,oper=0,res=0;
        // 每次扫描到的运算符
        char ch=' ';
        // 用于拼接多位数
        String keepNum="";
        // 开始扫描字符串
        while (true){
            // 得到表达式的每个字符
             ch = str.substring(index, index + 1).charAt(0);
            // 判断c是不是运算符
            if (operStack.isOper(ch)){
                if (operStack.isEmpty()){
                    // 为空的情况
                    operStack.push(ch);
                }else {
                    // 不为空的情况
                    // 判断栈中的优先级
                    int peek = operStack.peek();
                    int priority = operStack.priority(peek);
                    // 拿到当前运算符的优先级
                    int priority1 = operStack.priority(ch);
                    // 优先级大于栈中运算符的优先级
                    if (priority1<=priority){
                        // 弹出数字栈中的两个数字
                         num1 = numStack.pop();
                         num2=numStack.pop();
                         // 取出栈中栈顶的运算符
                        int pop = operStack.pop();
                        res=numStack.cal(num1,num2,pop);
                        // 将当前运算符压如栈顶
                        operStack.push(ch);
                         // 存入数字栈
                        numStack.push(res);
                    }else {
                        operStack.push(ch);
                    }
                }
            }else {
                // 数字直接进入数字栈,char-48=int
                //numStack.push(ch-48);
                // 当是多位数时，需要累加，往表达式后面多看一位，如果是操作符则入栈，是数字则不能入栈
                keepNum+=ch;
                // 判断下一位字符是不是数字
                if (index==str.length()-1){
                    numStack.push(Integer.parseInt(keepNum));
                }else {
                    if (operStack.isOper(str.substring(index + 1, index + 2).charAt(0))) {
                        // 是操作符，则入栈
                        numStack.push(Integer.parseInt(keepNum));
                        // 清空keepNum
                        keepNum = "";
                    }
                }

            }
            // 判断是否扫秒完成
            index++;
            if (index>=str.length()){
                break;
            }
        }
        // 扫面完成后，从符号栈和数字栈中扫描数字来计算
        while (true){
            // 如果符号栈为空，则数字栈中的数字只有一个就是结果
            if (operStack.isEmpty()){
                break;
            }
            num1=numStack.pop();
            num2=numStack.pop();
            oper=operStack.pop();
            res= numStack.cal(num1, num2, oper);
            numStack.push(res);
        }
        System.out.println(numStack.pop());
    }
}
class ArrayStack2{
    //  栈的大小
    private int maxSize;
    // 数组模拟栈，数据放在数组中
    private int[] stack;
    // top 表示栈顶，初始化为没有数据
    private int top=-1;
    // 初始化数组
    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        this.stack = new int[this.maxSize];
    }
    // 栈满了
    public boolean isFul(){
        return top==maxSize-1;
    }
    // 栈空
    public boolean isEmpty(){
        return top==-1;
    }
    // 入栈
    public void push(int value){
        // 判断栈是否满了
        if (this.isFul()){
            System.out.println("栈满了");
            return;
        }
        top++;
        stack[top]=value;
    }
    // 出栈
    public int pop(){
        // 栈是否为空
        if (isEmpty()){
            throw new RuntimeException("栈空，无法弹栈");
        }
        int value=stack[top];
        top--;
        return value;
    }
    // 返回当前栈顶值，但是不出站
    public int peek(){
        return stack[top];
    }
    // 遍历栈
    public void  list(){
        // 是否为空
        if(isEmpty()){
            System.out.println("没有数据，违法遍历");
            return;
        }
        for (int i = top; i >=0 ; i--) {
            System.out.println(stack[i]);
        }
    }
    // 扩展计算计算符的优先级
    public int priority(int oper){
        if (oper=='/'||oper=='*'){
            return 1;
        }else if (oper=='+'||oper=='-'){
            return 0;
        }else {
            throw new RuntimeException("符号错误");
        }
    }
    // 判断是否是一个运算符
    public boolean isOper(char var){
        return var=='+'||var=='-'||var=='*'||var=='/';
    }
    // 计算方法
    public int cal(int num1,int num2,int oper){
        int res=0;
        switch (oper){
            case '+':
                res=num2+num1;
                break;
            case '-':
                res=num2-num1;
                break;
            case '*':
                res=num2*num1;
                break;
            case '/':
                res=num2/num1;
                break;

        }
        return res;
    }

}

